﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Specialized;

using Layers;

namespace HoldemGame
{
    public enum LogicalOperation 
    {
            And,
            Or,
    };

    public class PredicateExpression<T>
    {
        private Predicate<T> _dgt;
        private Predicate<T> [] _args;

        public PredicateExpression(params Predicate<T>[] args)
        {
            _args = args;
        }

        public static Predicate<T> And(params Predicate<T>[] args)
        {
            PredicateExpression<T> f = new PredicateExpression<T>(args);
            f._dgt = f.And;
            return f.And;
        }

        public static Predicate<T> Or(params Predicate<T>[] args)
        {
            PredicateExpression<T> f = new PredicateExpression<T>(args);
            f._dgt = f.Or;
            return f.Or;
        }

        bool And(T arg){
            foreach (Predicate<T> pred in _args)
            {
                if(!pred(arg))
                    return false;
            }
            return true;
        }

        bool Or(T arg)
        {
           foreach (Predicate<T> pred in _args)
           {
                if(pred(arg))
                    return true;
           }
           return false;
        }
    }

    public class HoldemActionList : ObservableListWrapper<HoldemAction>
    {
        private HoldemActionHistory _src;
        private Predicate<HoldemAction> _filter;


        public HoldemActionList(HoldemActionHistory src, Predicate<HoldemAction> filter)
            : base(Factory.NewList<HoldemAction>())
        {
            _filter = filter;
            if(null!=src)
                SetSource(src);
        }

        public HoldemActionList() : this( null, null)
        {
        }

        public Predicate<HoldemAction> Filter
        {
            get { return _filter; }
            set { _filter = value; Update(); }
        }

        public HoldemActionHistory Source
        {
            get { return _src; }
            set { SetSource(value); }
        }

        private void SetSource(HoldemActionHistory h)
        {
            _src = h;
            _src.CollectionChanged += new NotifyCollectionChangedEventHandler(Source_Changed);
            Update();
        }

        void Source_Changed(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add)
            {
                foreach (HoldemAction a in e.NewItems)
                    if (_filter(a))
                        Add(a);
            }
            else
                Update();
        }

        public void Update()
        {
            _impl.Clear();
            OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
            bool added = false;
            foreach (HoldemAction ha in _src)
                if (_filter(ha))
                {
                    _impl.Add(ha);
                    added = true;
                }
            if(added)
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add,_impl));
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            foreach(HoldemAction ha in this)
            {
                sb.AppendFormat("{0}\n", ha);
            }
            return sb.ToString();
        }

        #region IListView<HoldemAction> Members

        public int Count
        {
            get { return _impl.Count; }
        }

        public HoldemAction this[int index]
        {
            get { return _impl[index]; }
        }

        #endregion

        #region IEnumerable<HoldemAction> Members

        public IEnumerator<HoldemAction> GetEnumerator()
        {
            return _impl.GetEnumerator();
        }

        #endregion


        public void Query()
        {
        }
       
    }


    public class HoldemActionHistory : HoldemActionList
    {
        private Game _game;

        public HoldemActionHistory(Game game) 
        {
            _game = game;
        }

        public void Subscribe()
        {
            _game.PostAction += new EventHandler<HoldemActionEventArgs>(Game_Action);
        }

        void Game_Action(object sender, HoldemActionEventArgs e)
        {
            Add(e.Action);
        }

        public HoldemActionList FilterBy(Predicate<HoldemAction> p)
        {
            HoldemActionList result = new HoldemActionList(this, p);
            return result;
        }

        public Predicate<HoldemAction> PlayerEquals(GamePlayer p)
        {
            return delegate(HoldemAction ha)
                {
                    PlayerAction pa = ha as PlayerAction;
                    return null!=pa && pa.Player==p;
                };
        }

    }

    
}